/**
 * @file STL_Scheduler.h
 * @author Derek Liu (yjkhtddx@sina.com)
 * @brief 
 * @version 0.1
 * @date 2021-03-04
 * 
 * @copyright Copyright Sci-Tech Laboratories (c) 2021
 * 
 */

#ifndef __STL_SCHEDULER_H__
#define __STL_SCHEDULER_H__

#include <functional>
#include <map>
#include <string>
#include <sys/time.h>
#include <stdio.h>
#include "STL_Tools.h"
#include <mutex>

namespace STL
{

    // typedef void (*STL_SchedulerCallback)(float);

    typedef std::function<void(float)> STL_SchedulerCallback;

    class STL_SchedulerObject
    {
    public:
        STL_SchedulerObject(STL_SchedulerCallback callback, float delay, bool paused, float interval, unsigned int repeat)
            : m_callback(callback), m_delay(delay), m_paused(paused), m_interval(interval), m_repeat(repeat), m_shouldDeleted(false)
        {
            struct timezone tz;
            gettimeofday(&m_lasttime, &tz);
        }
        ~STL_SchedulerObject() = default;

    public:
        void onUpdate(float t) { m_callback(t); }

    public:
        STL_SchedulerCallback m_callback;
        STL_SYNTHESIZE(std::string, m_cron, Cron);
        STL_SYNTHESIZE(float, m_delay, Delay);
        STL_SYNTHESIZE(bool, m_paused, Paused);
        STL_SYNTHESIZE(float, m_interval, Interval);
        STL_SYNTHESIZE(unsigned int, m_repeat, Repeat);
        // STL_SYNTHESIZE(struct timeval, m_lasttime, LastTime);
        STL_SYNTHESIZE(bool, m_shouldDeleted, ShouldDeleted);

    public:
        struct timeval m_lasttime;
        void setLastTime(struct timeval lasttime) { m_lasttime = lasttime; };
        struct timeval getLastTime() { return m_lasttime; };
    };

    class STL_Scheduler
    {
    public:
        static STL_Scheduler *getInstance();
        static void destroy();

    public:
        /**
         * @param cb 定时函数 std::function<void(float)>
         * @param interval 间隔(秒) 
         * @param repeat  循环(次) "-1" 永久执行
         * @param delay 延迟(秒) 第一次执行的延迟时间
         * @param paused 暂停(布尔) 是否暂停
         * @param key 标记(key值)
         */
        void schedule(STL_SchedulerCallback cb, float interval, unsigned int repeat, float delay, bool paused, std::string key);
        /**
         * @param cb 定时函数 std::function<void(float)>
         * @param interval 间隔(秒) 
         * @param key 标记(key值)
         */
        void setInterval(STL_SchedulerCallback cb, float interval, std::string key);
        /**
         * @param cb 定时函数 std::function<void(float)>
         * @param delay 延迟(秒) 
         * @param key 标记(key值)
         */
        void setTimeout(STL_SchedulerCallback cb, float delay, std::string key);
        //TODO void setCronTask(std::string cron, std::string key);
        /**
         * @param key 标记(key值)
         */
        void unschedule(std::string key);

        // void startWatchdog();
        // void stopWatchdog();
        // void updateWatchdog();

        // 阻塞循环调用函数
        void loop();
        // 线程循环调用函数
        void StartThreadLoop();

    private:
        STL_Scheduler();
        ~STL_Scheduler();
        void unscheduleAll();
        void updateSchedule();
        void run();

    private:
        static STL_Scheduler *m_instance;
        std::map<std::string, STL_SchedulerObject *> m_callbacks;
        std::mutex m_mutex;
        //    std::thread* m_thread;
        bool m_isRunning;
    };
}

#endif //__STL_SCHEDULER_H__